/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package net.huangp.dao;

import java.sql.SQLException;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
import javax.annotation.PostConstruct;
import net.huangp.domain.SMS;
import net.huangp.exception.SMSNotFoundException;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.Expression;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.stereotype.Repository;

/**
 *
 * @author Patrick Huang
 */
@Repository
public class SMSDAOHbnImpl implements SMSDAO{
    //--------------------------------------------------------------------------
    // Static Properties
    //--------------------------------------------------------------------------
    private static final Logger logger = LoggerFactory.getLogger(SMSDAOHbnImpl.class);

    protected static final String QUERY_COUNT_SMS = "select count(sms.id) from SMS sms";
    //--------------------------------------------------------------------------
    // Properties
    //--------------------------------------------------------------------------
    @Autowired
    private SessionFactory sessionFactory;
    private HibernateTemplate hibernateTemplate;
    // -------------------------------------------------------------------------
    // Implementation Methods
    // -------------------------------------------------------------------------
    @PostConstruct
    public void init(){
        assert(sessionFactory != null);
        hibernateTemplate = new HibernateTemplate(sessionFactory);
    }
    
    public void saveOrUpdateSMS(SMS sms) {
        hibernateTemplate.saveOrUpdate(sms);
    }

    public void deleteSMS(Long id) {
        hibernateTemplate.bulkUpdate("delete from SMS sms where sms.id = ?",id);
    }

    public SMS getSMS(Long id) {
        SMS sms = hibernateTemplate.get(SMS.class, id);
        if(sms == null){
            logger.error("can not find sms by id:[{}]",id);
            throw new SMSNotFoundException();
        }
        return sms;
    }

    public List<SMS> searchSMSByExample(final SMS exampleSms) {
        logger.debug("example sms:{}",exampleSms);
        Example example = Example.create(exampleSms);
        example.enableLike(MatchMode.ANYWHERE); //wildcard
        example.ignoreCase();
        //we exclude date and time first
        example.excludeProperty("smsDate").excludeProperty("smsTime");
        

        DetachedCriteria c = DetachedCriteria.forClass(SMS.class)
                                .add(example);
        //if smsDate is supplied, we create criteria using between
        if(exampleSms.getSmsDate() != null){
            Calendar theDate = new GregorianCalendar();
            theDate.setTime(exampleSms.getSmsDate());
            int year = theDate.get(Calendar.YEAR);
            int month = theDate.get(Calendar.MONTH);
            int date = theDate.get(Calendar.DATE);
            theDate.set(year, month, date, 0, 0, 0);

            logger.debug("search on the date:[{}]",theDate.getTime());
            c.add(Expression.eq("smsDate", theDate.getTime()))
                .addOrder( Order.desc("smsTime") );
            
        }
        
        List<SMS> results = hibernateTemplate.findByCriteria(c);
        if(results == null || results.size() == 0){
            logger.warn("can not find any sms with example sms:{}",exampleSms);
            throw new SMSNotFoundException();
        }
        return results;
    }

    public List<SMS> listSMS(final int start,final int max) {
        return hibernateTemplate.executeFind(new HibernateCallback(){
            private static final String QUERY = "from SMS sms order by sms.smsDate";
            //do in hibernate call back
            public List<SMS> doInHibernate(Session session)
                    throws HibernateException, SQLException {
                return session.createQuery(QUERY)
                        .setFirstResult(start)
                        .setMaxResults(max)
                        .list();
            }           
        });


    }

    public Long countSMS(){
        return (Long) hibernateTemplate.find(QUERY_COUNT_SMS).get(0);
    }
    // -------------------------------------------------------------------------
    // Mutator Methods
    // -------------------------------------------------------------------------
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

}
